home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / hobby / ast44src.zip / CHARTS2.C < prev    next >
C/C++ Source or Header  |  1995-02-11  |  30KB  |  896 lines

  1. /*
  2. ** Astrolog (Version 4.40) File: charts2.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
  6. ** (astara@u.washington.edu). Permission is granted to freely use and
  7. ** distribute these routines provided one doesn't sell, restrict, or
  8. ** profit from them in any way. Modification is allowed provided these
  9. ** notices remain with any altered or edited versions of the program.
  10. **
  11. ** The main planetary calculation routines used in this program have
  12. ** been Copyrighted and the core of this program is basically a
  13. ** conversion to C of the routines created by James Neely as listed in
  14. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  15. ** available from Matrix Software. The copyright gives us permission to
  16. ** use the routines for personal use but not to sell them or profit from
  17. ** them in any way.
  18. **
  19. ** The PostScript code within the core graphics routines are programmed
  20. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  21. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  22. **
  23. ** The extended accurate ephemeris databases and formulas are from the
  24. ** calculation routines in the program "Placalc" and are programmed and
  25. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  26. ** (alois@azur.ch). The use of that source code is subject to
  27. ** regulations made by Astrodienst Zurich, and the code is not in the
  28. ** public domain. This copyright notice must not be changed or removed
  29. ** by any user of this program.
  30. **
  31. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  32. ** X Window graphics initially programmed 10/23-29/1991.
  33. ** PostScript graphics initially programmed 11/29-30/1992.
  34. ** Last code change made 1/29/1995.
  35. */
  36.  
  37. #include "astrolog.h"
  38.  
  39.  
  40. /*
  41. ******************************************************************************
  42. ** Dual Chart Display Routines.
  43. ******************************************************************************
  44. */
  45.  
  46. /* Print out an aspect (or midpoint if -g0 switch in effect) grid of a      */
  47. /* relationship chart. This is similar to the ChartGrid() routine; however, */
  48. /* here we have both axes labeled with the planets for the two charts in    */
  49. /* question, instead of just a diagonal down the center for only one chart. */
  50.  
  51. void ChartGridRelation()
  52. {
  53.   char sz[cchSzDef];
  54.   int i, j, k, tot = cObj, temp;
  55.  
  56. #ifdef INTERPRET
  57.   if (us.fInterpret && !us.fGridConfig) {
  58.     InterpretGridRelation();
  59.     return;
  60.   }
  61. #endif
  62.   PrintSz(" 2>");
  63.   for (temp = 0, i = 1; i <= cObj; i++) if (!ignore[i]) {
  64.     PrintCh(chV);
  65.     AnsiColor(kObjA[i]);
  66.     sprintf(sz, "%c%c%c", chObj3(i)); PrintSz(sz);
  67.     AnsiColor(kDefault);
  68.     temp++;
  69.   }
  70.   PrintSz("\n1  ");
  71.   for (i = 1; i <= tot; i++) if (!ignore[i]) {
  72.     PrintCh(chV);
  73.     AnsiColor(kSignA(SFromZ(cp2.obj[i])));
  74.     sprintf(sz, "%2d%c", (int)cp2.obj[i] % 30, chDeg0); PrintSz(sz);
  75.     AnsiColor(kDefault);
  76.   }
  77.   PrintSz("\nV  ");
  78.   for (i = 1; i <= tot; i++) if (!ignore[i]) {
  79.     PrintCh(chV);
  80.     temp = SFromZ(cp2.obj[i]);
  81.     AnsiColor(kSignA(temp));
  82.     sprintf(sz, "%c%c%c", chSig3(temp)); PrintSz(sz);
  83.     AnsiColor(kDefault);
  84.   }
  85.   PrintL();
  86.   for (j = 1; j <= cObj; j++) if (!ignore[j])
  87.     for (k = 1; k <= 4; k++) {
  88.       if (k < 2)
  89.         PrintTab(chH, 3);
  90.       else if (k == 2) {
  91.         AnsiColor(kObjA[j]);
  92.         sprintf(sz, "%c%c%c", chObj3(j)); PrintSz(sz);
  93.       } else {
  94.         temp = SFromZ(cp1.obj[j]);
  95.         AnsiColor(kSignA(temp));
  96.         if (k == 3)
  97.           sprintf(sz, "%2d%c", (int)cp1.obj[j] - (temp-1)*30, chDeg0);
  98.         else
  99.           sprintf(sz, "%c%c%c", chSig3(temp));
  100.         PrintSz(sz);
  101.       }
  102.       if (k > 1)
  103.         AnsiColor(kDefault);
  104.       for (i = 1; i <= tot; i++) if (!ignore[i]) {
  105.         PrintCh((char)(k < 2 ? chC : chV));
  106.         temp = grid->n[i][j];
  107.         if (k > 1) {
  108.           if (i == j)
  109.             AnsiColor(kReverse);
  110.           AnsiColor(us.fGridConfig ? kSignA(temp) :
  111.             kAspA[temp]);
  112.         }
  113.         if (k < 2)
  114.           PrintTab(chH, 3);
  115.         else if (k == 2) {
  116.           if (us.fGridConfig)
  117.             sprintf(sz, "%c%c%c", chSig3(temp));
  118.           else
  119.             sprintf(sz, "%s", temp ? szAspectAbbrev[temp] : "   ");
  120.           PrintSz(sz);
  121.         } else if (k == 3) {
  122.           if (us.fGridConfig) {
  123.             sprintf(sz, "%2d%c", grid->v[i][j]/60, chDeg0); PrintSz(sz);
  124.           } else
  125.             if (grid->n[i][j]) {
  126.               if (grid->v[i][j] < 6000)
  127.                 sprintf(sz, "%c%2d", us.fAppSep ?
  128.                   (grid->v[i][j] < 0 ? 'a' : 's') :
  129.                   (grid->v[i][j] < 0 ? '-' : '+'), abs(grid->v[i][j])/60);
  130.               else
  131.                 sprintf(sz, "%3d", abs(temp)/60);
  132.               PrintSz(sz);
  133.             } else
  134.               PrintSz("   ");
  135.         } else {
  136.           if (grid->n[i][j]) {
  137.             sprintf(sz, "%02d'", abs(grid->v[i][j])%60); PrintSz(sz);
  138.           } else
  139.             PrintSz("   ");
  140.         }
  141.         AnsiColor(kDefault);
  142.       }
  143.       PrintL();
  144.     }
  145. }
  146.  
  147.  
  148. /* Display all aspects between objects in the relationship comparison chart, */
  149. /* one per line, in sorted order based on the total "power" of the aspects,  */
  150. /* as specified with the -r0 -a switch combination.                          */
  151.  
  152. void ChartAspectRelation()
  153. {
  154.   char sz[cchSzDef];
  155.   int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
  156.   real ip, jp;
  157.  
  158.   loop {
  159.     phi = -1;
  160.  
  161.     /* Search for the next most powerful aspect in the aspect grid. */
  162.  
  163.     for (i = 1; i <= cObj; i++) if (!ignore[i])
  164.       for (j = 1; j <= cObj; j++) if (!ignore[j])
  165.         if (k = grid->n[i][j]) {
  166.           ip = i <= oNorm ? objectinf[i] : 2.5;
  167.           jp = j <= oNorm ? objectinf[j] : 2.5;
  168.           p = (int)(aspectinf[k]*(ip+jp)/2.0*
  169.             (1.0-RAbs((real)(grid->v[i][j]))/60.0/aspectorb[k])*1000.0);
  170.           if ((p < pcut || (p == pcut && (i > icut ||
  171.             (i == icut && j > jcut)))) && p > phi) {
  172.             ihi = i; jhi = j; phi = p; ahi = k;
  173.           }
  174.         }
  175.     if (phi < 0)    /* Exit when no less powerful aspect found. */
  176.       break;
  177.     pcut = phi; icut = ihi; jcut = jhi;
  178.     count++;                              /* Display the current aspect.   */
  179. #ifdef INTERPRET
  180.     if (us.fInterpret) {                  /* Interpret it if -I in effect. */
  181.       InterpretAspectRelation(jhi, ihi);
  182.       continue;
  183.     }
  184. #endif
  185.     sprintf(sz, "%3d: ", count); PrintSz(sz);
  186.     PrintAspect(jhi, SFromZ(cp1.obj[jhi]), (int)RSgn(cp1.dir[jhi]), ahi,
  187.       ihi, SFromZ(cp2.obj[ihi]), (int)RSgn(cp2.dir[ihi]), 'A');
  188.     k = grid->v[ihi][jhi];
  189.     AnsiColor(k < 0 ? kWhite : kLtGray);
  190.     sprintf(sz, "- orb: %c%d,%02d'",
  191.       us.fAppSep ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
  192.       abs(k)/60, abs(k)%60); PrintSz(sz);
  193.     AnsiColor(kDkGreen);
  194.     sprintf(sz, " - power:%6.2f\n", (real)phi/1000.0); PrintSz(sz);
  195.     AnsiColor(kDefault);
  196.   }
  197. }
  198.  
  199.  
  200. /* Display locations of all midpoints between objects in the relationship */
  201. /* comparison chart, one per line, in sorted zodiac order from zero Aries */
  202. /* onward, as specified with the -r0 -m switch combination.               */
  203.  
  204. void ChartMidpointRelation()
  205. {
  206.   char sz[cchSzDef];
  207.   int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, count = 0;
  208.  
  209.   loop {
  210.     mlo = 21600;
  211.  
  212.     /* Search for the next closest midpoint farther down in the zodiac. */ 
  213.  
  214.     for (i = 1; i <= cObj; i++) if (!ignore[i])
  215.       for (j = 1; j <= cObj; j++) if (!ignore[j]) {
  216.         m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
  217.         if ((m > mcut || (m == mcut && (i > icut ||
  218.           (i == icut && j > jcut)))) && m < mlo) {
  219.           ilo = i; jlo = j; mlo = m;
  220.         }
  221.       }
  222.     if (mlo >= 21600)    /* Exit when no midpoint farther in zodiac found. */
  223.       break;
  224.     mcut = mlo; icut = ilo; jcut = jlo;
  225.     count++;                               /* Display the current midpoint. */
  226. #ifdef INTERPRET
  227.     if (us.fInterpret) {                   /* Interpret it if -I in effect. */
  228.       InterpretMidpointRelation(ilo, jlo);
  229.       continue;
  230.     }
  231. #endif
  232.     sprintf(sz, "%4d: ", count); PrintSz(sz);
  233.     PrintZodiac((real)mlo/60.0);
  234.     PrintCh(' ');
  235.     PrintAspect(ilo, SFromZ(cp1.obj[ilo]), (int)RSgn(cp1.dir[ilo]), 0,
  236.       jlo, SFromZ(cp2.obj[jlo]), (int)RSgn(cp2.dir[jlo]), 'M');
  237.     AnsiColor(kDefault);
  238.     m = (int)(MinDistance(cp1.obj[ilo], cp2.obj[jlo])*60.0);
  239.     sprintf(sz, "-%4d%c%02d' degree span.\n", m/60, chDeg1, m%60);
  240.     PrintSz(sz);
  241.   }
  242. }
  243.  
  244.  
  245. /* Calculate any of the various kinds of relationship charts. This involves */
  246. /* reading in and storing the planet and house positions for both charts,   */
  247. /* and then combining them in the main single chart in the proper manner.   */
  248. /* If the parameter 'fFile' is on, then we read the info for the two charts */
  249. /* from files, otherwise use the info in preset "core" and "second" charts. */
  250.  
  251. void CastRelation(fFile)
  252. bool fFile;
  253. {
  254.   byte ignoreT[objMax];
  255.   CI ciT;
  256.   int i;
  257.   real ratio, t1, t2, t;
  258.  
  259.   /* Read in and cast the first chart. */
  260.  
  261.   if (fFile)
  262.     FInputData(is.szFile);
  263.   ciT = ciCore;
  264.   if (fFile)
  265.     ciTwin = ciCore;
  266.   else
  267.     ciCore = ciTwin;
  268.   t1 = CastChart(fTrue);
  269.   for (i = 1; i <= cSign; i++) {
  270.     cp1.cusp[i] = house[i];
  271.     cp1.house[i] = inhouse[i];
  272.   }
  273.   for (i = 1; i <= cObj; i++) {
  274.     cp1.obj[i] = planet[i];
  275.     cp1.alt[i] = planetalt[i];
  276.     cp1.dir[i] = ret[i];
  277.   }
  278.  
  279.   /* Read in the second chart. */
  280.  
  281.   if (fFile) {
  282.     FInputData(is.szFile2);
  283.     if (us.nRel == rcProgress) {
  284.       us.fProgress = fTrue;
  285.       is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ);
  286.       ciCore = ciT;
  287.     }
  288.   } else
  289.     ciCore = ciT;
  290.   ciMain = ciCore;
  291.   if (us.nRel == rcTransit)
  292.     for (i = 1; i <= cObj; i++) {
  293.       ignoreT[i] = ignore[i];
  294.       ignore[i] = ignore[i] && ignore2[i];
  295.     }
  296.   t2 = CastChart(fTrue);
  297.   if (us.nRel == rcTransit)
  298.     for (i = 1; i <= cObj; i++)
  299.       ignore[i] = ignoreT[i];
  300.   for (i = 1; i <= cSign; i++) {
  301.     cp2.cusp[i] = house[i];
  302.     cp2.house[i] = inhouse[i];
  303.   }
  304.   for (i = 1; i <= cObj; i++) {
  305.     cp2.obj[i] = planet[i];
  306.     cp2.alt[i] = planetalt[i];
  307.     cp2.dir[i] = ret[i];
  308.   }
  309.  
  310.   /* Now combine the two charts based on what relation we are doing.   */
  311.   /* For the standard -r synastry chart, use the house cusps of chart1 */
  312.   /* and the planets positions of chart2.                              */
  313.  
  314.   ratio = (real)us.nRatio1 / ((real)(us.nRatio1 + us.nRatio2));
  315.   if (us.nRel <= rcSynastry)
  316.     for (i = 1; i <= cSign; i++)
  317.       house[i] = cp1.cusp[i];
  318.  
  319.   /* For the -rc composite chart, take the midpoints of the planets/houses. */
  320.  
  321.   else if (us.nRel == rcComposite) {
  322.     for (i = 1; i <= cObj; i++) {
  323.       planet[i] = Ratio(cp1.obj[i], cp2.obj[i], ratio);
  324.       if (RAbs(cp2.obj[i] - cp1.obj[i]) > rDegHalf)
  325.         planet[i] = Mod(planet[i] + rDegMax*ratio);
  326.       planetalt[i] = Ratio(cp1.alt[i], cp2.alt[i], ratio);
  327.       ret[i] = Ratio(cp1.dir[i], cp2.dir[i], ratio);
  328.     }
  329.     for (i = 1; i <= cSign; i++) {
  330.       house[i] = Ratio(cp1.cusp[i], cp2.cusp[i], ratio);
  331.       if (RAbs(cp2.cusp[i] - cp1.cusp[i]) > rDegHalf)
  332.         house[i] = Mod(house[i] + rDegMax*ratio);
  333.     }
  334.  
  335.     /* Make sure we don't have any 180 degree errors in house cusp    */
  336.     /* complement pairs, which may happen if the cusps are far apart. */
  337.  
  338.     for (i = 1; i <= cSign; i++)
  339.       if (MinDistance(house[sCap], Mod(house[i]-ZFromS(i+3))) > rDegQuad)
  340.         house[i] = Mod(house[i]+rDegHalf);
  341.     for (i = 1; i <= cSign; i++)
  342.       if (RAbs(MinDistance(house[i], planet[oAsc - 1 + i])) > rDegQuad)
  343.         planet[oAsc - 1 + i] = Mod(planet[oAsc - 1 + i]+rDegHalf);
  344.  
  345.   /* For the -rm time space midpoint chart, calculate the midpoint time and */
  346.   /* place between the two charts and then recast for the new chart info.   */
  347.  
  348.   } else if (us.nRel == rcMidpoint) {
  349.     T = Ratio(t1, t2, ratio);
  350.     t = (T*36525.0)+rRound; is.JD = RFloor(t)+2415020.0; TT = RFract(t)*24.0;
  351.     ZZ = Ratio(DecToDeg(ciT.zon), DecToDeg(Zon), ratio);
  352.     SS = Ratio(DecToDeg(ciT.dst), DecToDeg(Dst), ratio);
  353.     TT -= ZZ;
  354.     if (TT < 0.0) {
  355.       TT += 24.0; is.JD -= 1.0;
  356.     }
  357.     JulianToMdy(is.JD, &MM, &DD, &YY);
  358.     OO = Ratio(DecToDeg(ciT.lon), DecToDeg(Lon), ratio);
  359.     if (RAbs(Lon-ciT.lon) > rDegHalf)
  360.       OO = Mod(OO+rDegMax*ratio);
  361.     AA = Ratio(DecToDeg(ciT.lat), DecToDeg(Lat), ratio);
  362.     TT = DegToDec(TT); SS = DegToDec(SS); ZZ = DegToDec(ZZ);
  363.     OO = DegToDec(OO); AA = DegToDec(AA);
  364.     ciMain = ciCore;
  365.     CastChart(fTrue);
  366.  
  367.   /* There are a couple of non-astrological charts, which only require the */
  368.   /* number of days that have passed between the two charts to be done.    */
  369.  
  370.   } else
  371.     is.JD = RAbs(t2-t1)*36525.0;
  372.   ComputeInHouses();
  373. }
  374.  
  375.  
  376. /*
  377. ******************************************************************************
  378. ** Other Chart Display Routines.
  379. ******************************************************************************
  380. */
  381.  
  382. /* Given two objects and an aspect between them, or an object and a sign  */
  383. /* that it's entering, print if this is a "major" event, such as a season */
  384. /* change or major lunar phase. This is called from the ChartInDay()      */
  385. /* searching and influence routines. Do an interpretation if need be too. */
  386.  
  387. void PrintInDay(source, aspect, dest)
  388. int source, aspect, dest;
  389. {
  390.   if (aspect == aSig) {
  391.     if (source == oSun) {
  392.       AnsiColor(kWhite);
  393.       if (dest == 1)
  394.         PrintSz(" (Vernal Equinox)");     /* If the Sun changes sign, */
  395.       else if (dest == 4)                 /* then print out if this   */
  396.         PrintSz(" (Summer Solstice)");    /* is a season change.      */
  397.       else if (dest == 7)
  398.         PrintSz(" (Autumnal Equinox)");
  399.       else if (dest == 10)
  400.         PrintSz(" (Winter Solstice)");
  401.     }
  402.   } else if (aspect > 0) {
  403.     if (source == oSun && dest == oMoo) {
  404.       if (aspect <= aSqu)
  405.         AnsiColor(kWhite);
  406.       if (aspect == aCon)
  407.         PrintSz(" (New Moon)");     /* Print out if the present */
  408.       else if (aspect == aOpp)      /* aspect is a New, Full,   */
  409.         PrintSz(" (Full Moon)");    /* or Half Moon.            */
  410.       else if (aspect == aSqu)
  411.         PrintSz(" (Half Moon)");
  412.     }
  413.   }
  414.   PrintL();
  415.  
  416. #ifdef INTERPRET
  417.   if (us.fInterpret)
  418.     InterpretInDay(source, aspect, dest);
  419. #endif
  420.   AnsiColor(kDefault);
  421. }
  422.  
  423.  
  424. /* Given two objects and an aspect (or one object, and an event such as a */
  425. /* sign or direction change) display the configuration in question. This  */
  426. /* is called by the many charts which list aspects among items, such as   */
  427. /* the -a aspect lists, -m midpoint lists, -d aspect in day search and    */
  428. /* influence charts, and -t transit search and influence charts.          */
  429.  
  430. void PrintAspect(obj1, sign1, ret1, asp, obj2, sign2, ret2, chart)
  431. int obj1, sign1, ret1, asp, obj2, sign2, ret2;
  432. char chart;
  433. {
  434.   char sz[cchSzDef];
  435.  
  436.   AnsiColor(kObjA[obj1]);
  437.   if (chart == 't' || chart == 'T')
  438.     PrintSz("trans ");
  439.   else if (chart == 'e' || chart == 'u' || chart == 'U')
  440.     PrintSz("progr ");
  441.   sprintf(sz, "%7.7s", szObjName[obj1]); PrintSz(sz);
  442.   AnsiColor(kSignA(sign1));
  443.   sprintf(sz, " %c%c%c%c%c",
  444.     ret1 > 0 ? '(' : (ret1 < 0 ? '[' : '<'), chSig3(sign1),
  445.     ret1 > 0 ? ')' : (ret1 < 0 ? ']' : '>')); PrintSz(sz);
  446.   AnsiColor(asp > 0 ? kAspA[asp] : kWhite);
  447.   PrintCh(' ');
  448.   if (asp == aSig)
  449.     sprintf(sz, "-->");                        /* Print a sign change. */
  450.   else if (asp == aDir)
  451.     sprintf(sz, "S/%c", obj2 ? chRet : 'D');   /* Print a direction change. */
  452.   else if (asp == 0)
  453.     sprintf(sz, chart == 'm' ? "&" : "with");
  454.   else
  455.     sprintf(sz, "%s", szAspectAbbrev[asp]);    /* Print an aspect. */
  456.   PrintSz(sz);
  457.   if (asp != aDir)
  458.     PrintCh(' ');
  459.   if (chart == 'A')
  460.     PrintSz("with ");
  461.   if (asp == aSig) {
  462.     AnsiColor(kSignA(obj2));
  463.     sprintf(sz, "%s", szSignName[obj2]); PrintSz(sz);
  464.   } else if (asp >= 0) {
  465.     AnsiColor(kSignA(sign2));
  466.     if (chart == 't' || chart == 'u' || chart == 'T' || chart == 'U')
  467.       PrintSz("natal ");
  468.     sprintf(sz, "%c%c%c%c%c ",
  469.       ret2 > 0 ? '(' : (ret2 < 0 ? '[' : '<'), chSig3(sign2),
  470.       ret2 > 0 ? ')' : (ret2 < 0 ? ']' : '>')); PrintSz(sz);
  471.     AnsiColor(kObjA[obj2]);
  472.     sprintf(sz, "%.10s", szObjName[obj2]); PrintSz(sz);
  473.   }
  474.   if (chart == 'D' || chart == 'T' || chart == 'U' ||
  475.     chart == 'a' || chart == 'A' || chart == 'm' || chart == 'M')
  476.     PrintTab(' ', 10-CchSz(szObjName[obj2]));
  477. }
  478.  
  479.  
  480. /* Based on the given chart information, display all the aspects taking   */
  481. /* place in the chart, as specified with the -D switch. The aspects are   */
  482. /* printed in order of influence determined by treating them as happening */
  483. /* outside among transiting planets, such that rare outer planet aspects  */
  484. /* are given more power than common ones among inner planets. (This is    */
  485. /* almost identical to the -a list, except the influences are different.) */
  486.  
  487. void ChartInDayInfluence()
  488. {
  489.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  490.   real power[MAXINDAY];
  491.   char sz[cchSzDef];
  492.   int occurcount = 0, i, j, k, l, m;
  493.  
  494.   /* Go compute the aspects in the chart. */
  495.  
  496.   i = us.fAppSep;
  497.   us.fAppSep = fTrue;     /* We always want applying vs. separating orbs. */
  498.   FCreateGrid(fFalse);
  499.   us.fAppSep = i;
  500.  
  501.   /* Search through the grid and build up the list of aspects. */
  502.  
  503.   for (j = 2; j <= cObj; j++) {
  504.     if (ignore[j])
  505.       continue;
  506.     for (i = 1; i < j; i++) {
  507.       if (ignore[i] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  508.         continue;
  509.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  510.       l = grid->v[i][j];
  511.       power[occurcount] =
  512.         ((i <= oNorm ? transitinf[i] : 2.0)/4.0)*
  513.         ((j <= oNorm ? transitinf[j] : 2.0)/4.0)*
  514.         aspectinf[k]*(1.0-(real)abs(l)/60.0/GetOrb(i, j, k));
  515.       occurcount++;
  516.     }
  517.   }
  518.  
  519.   /* Sort aspects by order of influence. */
  520.  
  521.   for (i = 1; i < occurcount; i++) {
  522.     j = i-1;
  523.     while (j >= 0 && power[j] < power[j+1]) {
  524.       SwapN(source[j], source[j+1]);
  525.       SwapN(aspect[j], aspect[j+1]);
  526.       SwapN(dest[j], dest[j+1]);
  527.       SwapR(&power[j], &power[j+1]);
  528.       j--;
  529.     }
  530.   }
  531.  
  532.   /* Now display each aspect line. */
  533.  
  534.   for (i = 0; i < occurcount; i++) {
  535.     sprintf(sz, "%3d: ", i+1); PrintSz(sz);
  536.     j = source[i]; k = aspect[i]; l = dest[i];
  537.     PrintAspect(
  538.       j, SFromZ(planet[j]), (int)RSgn(ret[j]), k,
  539.       l, SFromZ(planet[l]), (int)RSgn(ret[l]), 'D');
  540.     m = grid->v[j][l];
  541.     AnsiColor(m < 0 ? kWhite : kLtGray);
  542.     sprintf(sz, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  543.       abs(m)/60, chDeg1, abs(m)%60); PrintSz(sz);
  544.     AnsiColor(kDkGreen);
  545.     sprintf(sz, " - power:%6.2f", power[i]); PrintSz(sz);
  546.     PrintInDay(j, k, l);
  547.   }
  548. }
  549.  
  550.  
  551. /* Given an arbitrary day, determine what aspects are made between this */
  552. /* transiting chart and the given natal chart, as specified with the -T */
  553. /* switch, and display the transits in order sorted by influence.       */
  554.  
  555. void ChartTransitInfluence(fProg)
  556. bool fProg;
  557. {
  558.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  559.   real power[MAXINDAY];
  560.   byte ignore3[objMax];
  561.   char sz[cchSzDef];
  562.   int occurcount = 0, i, j, k, l, m;
  563.  
  564.   /* Cast the natal and transiting charts as with a relationship chart. */
  565.  
  566.   for (i = 1; i <= cSign; i++)
  567.     cp1.cusp[i] = house[i];
  568.   for (i = 1; i <= cObj; i++) {
  569.     cp1.obj[i] = planet[i];
  570.     cp1.dir[i] = ret[i];
  571.   }
  572.   ciCore = ciTwin;
  573.   if (us.fProgress = fProg) {
  574.     is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ);
  575.     ciCore = ciMain;
  576.   }
  577.   CastChart(fTrue);
  578.   for (i = 1; i <= cSign; i++)
  579.     cp2.cusp[i] = house[i];
  580.   for (i = 1; i <= cObj; i++) {
  581.     cp2.obj[i] = planet[i];
  582.     cp2.dir[i] = ret[i];
  583.   }
  584.  
  585.   /* Do a relationship aspect grid to get the transits. We have to make and */
  586.   /* restore three changes to get it right for this chart. (1) We make the  */
  587.   /* natal planets have zero velocity so applying vs. separating is only a  */
  588.   /* function of the transiter. (2) We force applying vs. separating orbs   */
  589.   /* regardless if -ga or -ma is in effect or not. (3) Finally we tweak the */
  590.   /* main restrictions to allow for transiting objects not restricted.      */
  591.  
  592.   for (i = 1; i <= cObj; i++) {
  593.     ret[i] = cp1.dir[i];
  594.     cp1.dir[i] = 0.0;
  595.     ignore3[i] = ignore[i];
  596.     ignore[i] = ignore[i] && ignore2[i];
  597.   }
  598.   i = us.fAppSep;
  599.   us.fAppSep = fTrue;
  600.   FCreateGridRelation(fFalse);
  601.   us.fAppSep = i;
  602.   for (i = 1; i <= cObj; i++) {
  603.     cp1.dir[i] = ret[i];
  604.     ignore[i] = ignore3[i];
  605.   }
  606.  
  607.   /* Loop through the grid, and build up a list of the valid transits. */
  608.  
  609.   for (i = 1; i <= oNorm; i++) {
  610.     if (ignore2[i] || !FThing(i))
  611.       continue;
  612.     for (j = 1; j <= cObj; j++) {
  613.       if (ignore[j] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  614.         continue;
  615.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  616.       l = grid->v[i][j];
  617.       power[occurcount] = transitinf[i]*
  618.         ((j <= oNorm ? objectinf[j] : 2.0)/4.0)*aspectinf[k]*
  619.         (1.0-(real)abs(l)/60.0/GetOrb(i, j, k));
  620.       occurcount++;
  621.     }
  622.   }
  623.  
  624.   /* After all transits located, sort them by their total power. */
  625.  
  626.   for (i = 1; i < occurcount; i++) {
  627.     j = i-1;
  628.     while (j >= 0 && power[j] < power[j+1]) {
  629.       SwapN(source[j], source[j+1]);
  630.       SwapN(aspect[j], aspect[j+1]);
  631.       SwapN(dest[j], dest[j+1]);
  632.       SwapR(&power[j], &power[j+1]);
  633.       j--;
  634.     }
  635.   }
  636.  
  637.   /* Now loop through list and display each transit in effect at the time. */
  638.  
  639.   for (i = 0; i < occurcount; i++) {
  640.     k = aspect[i];
  641.     l = source[i];
  642.     sprintf(sz, "%3d: ", i+1); PrintSz(sz);
  643.     j = SFromZ(cp2.obj[l]);
  644.     PrintAspect(l, j, (int)RSgn(cp2.dir[l]), k,
  645.       dest[i], SFromZ(cp1.obj[dest[i]]), (int)RSgn(cp1.dir[dest[i]]),
  646.       (char)(fProg ? 'U' : 'T'));
  647.     m = grid->v[l][dest[i]];
  648.     AnsiColor(m < 0 ? kWhite : kLtGray);
  649.     sprintf(sz, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  650.       abs(m)/60, chDeg1, abs(m)%60); PrintSz(sz);
  651.     AnsiColor(kDkGreen);
  652.     sprintf(sz, " - power:%6.2f", power[i]); PrintSz(sz);
  653.     if (k == aCon && l == dest[i]) {    /* Print a small "R" for returns. */
  654.       AnsiColor(kWhite);
  655.       PrintSz(" R");
  656.     }
  657.     PrintL();
  658. #ifdef INTERPRET
  659.     if (us.fInterpret)
  660.       InterpretTransit(l, k, dest[i]);
  661. #endif
  662.     AnsiColor(kDefault);
  663.   }
  664. }
  665.  
  666.  
  667. /* Given the zodiac location of a planet in the sky and its declination,   */
  668. /* and a location on the Earth, compute the azimuth and altitude of where  */
  669. /* on the local horizon sky the planet would appear to one at the given    */
  670. /* location. A reference MC position at Greenwich is also needed for this. */
  671.  
  672. void EclToHorizon(azi, alt, planet, planetalt, lon, lat, mc)
  673. real *azi, *alt, planet, planetalt, lon, lat, mc;
  674. {
  675.   real lonz, latz;
  676.  
  677.   lonz = RFromD(planet); latz = RFromD(planetalt);
  678.   EclToEqu(&lonz, &latz);
  679.   lonz = RFromD(Mod(DFromR(mc-lonz+lon)));
  680.   lonz = RFromD(Mod(DFromR(lonz-lon+rPiHalf)));
  681.   EquToLocal(&lonz, &latz, rPiHalf-lat);
  682.   *azi = rDegMax-DFromR(lonz); *alt = DFromR(latz);
  683. }
  684.  
  685.  
  686. /* Display a calendar for the given month in the chart, as specified with  */
  687. /* with the -K switch. When color is on, the title is white, weekends are  */
  688. /* highlighted in red, and the specific day in the chart is colored green. */
  689.  
  690. void ChartCalendarMonth()
  691. {
  692.   char sz[cchSzDef];
  693.   int i, j, k;
  694.  
  695.   AnsiColor(kWhite);
  696.   PrintTab(' ', 16-CchSz(szMonth[Mon]) >> 1);
  697.   sprintf(sz, "%s%5d\n", szMonth[Mon], Yea); PrintSz(sz);
  698.   for (i = 0; i < 7; i++) {
  699.     sprintf(sz, "%c%c%c", szDay[i][0], szDay[i][1], i < 6 ? ' ' : '\n');
  700.     PrintSz(sz);
  701.   }
  702.   j = DayOfWeek(Mon, 1, Yea);
  703.   AnsiColor(kDefault);
  704.   for (i = 0; i < j; i++) {
  705.     if (i == 0)
  706.       AnsiColor(kRainbowA[1]);
  707.     PrintSz("-- ");
  708.     if (i == 0)
  709.       AnsiColor(kDefault);
  710.   }
  711.   k = DayInMonth(Mon, Yea);
  712.   for (i = 1; i <= k; i = AddDay(Mon, i, Yea, 1)) {
  713.     if (i == (int)Day)
  714.       AnsiColor(kRainbowA[4]);
  715.     else if (j == 0 || j == 6)
  716.       AnsiColor(kRainbowA[1]);
  717.     sprintf(sz, "%2d", i); PrintSz(sz);
  718.     if (j == 0 || j == 6 || i == Day)
  719.       AnsiColor(kDefault);
  720.     if (j < 6) {
  721.       j++;
  722.       PrintCh(' ');
  723.     } else {
  724.       j = 0;
  725.       PrintL();
  726.     }
  727.   }
  728.   while (j > 0 && j < 7) {
  729.     if (j == 6)
  730.       AnsiColor(kRainbowA[1]);
  731.     j++;
  732.     sprintf(sz, "--%c", j < 7 ? ' ' : '\n'); PrintSz(sz);
  733.   }
  734.   AnsiColor(kDefault);
  735. }
  736.  
  737.  
  738. /* Display a calendar for the entire year given in the chart, as specified */
  739. /* with the -Ky switch. This is just like twelve of the individual month   */
  740. /* calendars above displayed together, with same color highlights and all. */
  741.  
  742. void ChartCalendarYear()
  743. {
  744.   char sz[cchSzDef];
  745.   int r, w, c, m, d, dy, p[3], l[3], n[3];
  746.  
  747.   dy = DayOfWeek(1, 1, Yea);
  748.   for (r = 0; r < 4; r++) {     /* Loop over one set of three months */
  749.     AnsiColor(kWhite);
  750.     for (c = 0; c < 3; c++) {
  751.       m = r*3+c+1;
  752.       PrintTab(' ', 16-CchSz(szMonth[m]) >> 1);
  753.       sprintf(sz, "%s%5d", szMonth[m], Yea); PrintSz(sz);
  754.       if (c < 2)
  755.         PrintTab(' ', 20 + MONTHSPACE -
  756.           (16-CchSz(szMonth[m]) >> 1) - CchSz(szMonth[m]) - 5);
  757.     }
  758.     PrintL();
  759.     for (c = 0; c < 3; c++) {
  760.       for (d = 0; d < 7; d++) {
  761.         sprintf(sz, "%c%c%c", szDay[d][0], szDay[d][1],
  762.           d < 6 || c < 2 ? ' ' : '\n'); PrintSz(sz);
  763.       }
  764.       if (c < 2)
  765.         PrintTab(' ', MONTHSPACE-1);
  766.       m = r*3+c+1;
  767.       p[c] = dy % 7;
  768.       l[c] = DayInMonth(m, Yea);
  769.       n[c] = 0;
  770.       dy += DaysInMonth(m, Yea);
  771.     }
  772.     for (w = 0; w < 6; w++) {      /* Loop over one set of week rows */
  773.       for (c = 0; c < 3; c++) {    /* Loop over one week in a month  */
  774.         m = r*3+c+1;
  775.         d = 0;
  776.         if (w == 0)
  777.           while (d < p[c]) {
  778.             if (d == 0)
  779.               AnsiColor(kRainbowA[1]);
  780.             PrintSz("-- ");
  781.             if (d == 0)
  782.               AnsiColor(kDefault);
  783.             d++;
  784.           }
  785.         AnsiColor(kDefault);
  786.         while (d < 7 && n[c] < l[c]) {
  787.           n[c] = AddDay(m, n[c], Yea, 1);
  788.           if (n[c] == Day && m == Mon)
  789.             AnsiColor(kRainbowA[4]);
  790.           else if (d == 0 || d == 6)
  791.             AnsiColor(kRainbowA[1]);
  792.           sprintf(sz, "%2d%c", n[c], d < 6 || c < 2 ? ' ' : '\n');
  793.           PrintSz(sz);
  794.           if (d == 0 || d == 6 || (n[c] == Day && m == Mon))
  795.             AnsiColor(kDefault);
  796.           d++;
  797.         }
  798.         while (d < 7) {
  799.           if (d == 0 || d == 6)
  800.             AnsiColor(kRainbowA[1]);
  801.           sprintf(sz, "--%c", d < 6 || c < 2 ? ' ' : '\n'); PrintSz(sz);
  802.           if (d == 0)
  803.             AnsiColor(kDefault);
  804.           d++;
  805.         }
  806.         if (c < 2)
  807.           PrintTab(' ', MONTHSPACE-1);
  808.       }
  809.     }
  810.     if (r < 3)
  811.       PrintL();
  812.   }
  813.   AnsiColor(kDefault);
  814. }
  815.  
  816.  
  817. /* Display either a biorhythm chart or the time difference in various units */
  818. /* between two charts, i.e. two types of relationship "charts" that aren't  */
  819. /* related in any way to planetary positions, as specified by either the    */
  820. /* -rb or -rd switches, respectively.                                       */
  821.  
  822. void DisplayRelation()
  823. {
  824.   char sz[cchSzDef];
  825.   int i;
  826. #ifdef BIORHYTHM
  827.   int j;
  828.   real k, l;
  829. #endif
  830.  
  831.   /* If we are calculating the difference between two dates, then display */
  832.   /* the value and return, as with the -rd switch.                        */
  833.  
  834.   if (us.nRel == rcDifference) {
  835.     PrintSz("Differences between the dates in the two charts:\n");
  836.     for (i = 1; i <= 7; i++) {
  837.       AnsiColor(kRainbowA[i]);
  838.       switch (i) {
  839.       case 1: sprintf(sz, "Years  : %.0f", is.JD/365.25);      break;
  840.       case 2: sprintf(sz, "Months : %.0f", is.JD/(365.25/12)); break;
  841.       case 3: sprintf(sz, "Weeks  : %.0f", is.JD/7.0);         break;
  842.       case 4: sprintf(sz, "Days   : %.0f", is.JD);             break;
  843.       case 5: sprintf(sz, "Hours  : %.0f", is.JD*24.0);        break;
  844.       case 6: sprintf(sz, "Minutes: %.0f", is.JD*24.0*60.0);   break;
  845.       case 7: sprintf(sz, "Seconds: %.0f", is.JD*24.0*3600.0); break;
  846.       }
  847.       PrintSz(sz);
  848.       PrintL();
  849.     }
  850.     AnsiColor(kDefault);
  851.     return;
  852.   }
  853.  
  854. #ifdef BIORHYTHM
  855.   /* If we are doing a biorhythm (-rb switch), then we'll calculate it for */
  856.   /* someone born on the older date, at the time of the younger date. Loop */
  857.   /* through the week preceeding and following the date in question.       */
  858.  
  859.   is.JD = RFloor(is.JD + rRound);
  860.   for (is.JD -= 7.0, i = -7; i <= 7; i++, is.JD += 1.0) {
  861.     if (i == 0)
  862.       AnsiColor(kWhite);
  863.     else if (i == 1)
  864.       AnsiColor(kDefault);
  865.     sprintf(sz, "T%c%d Day%c:",
  866.       i < 0 ? '-' : '+', abs(i), abs(i) != 1 ? 's' : ' '); PrintSz(sz);
  867.     for (j = 1; j <= 3; j++) {
  868.       PrintCh(' ');
  869.       switch (j) {
  870.       case 1: k = brPhy; AnsiColor(kRed);   PrintSz("Physical");     break;
  871.       case 2: k = brEmo; AnsiColor(kBlue);  PrintSz("Emotional");    break;
  872.       case 3: k = brInt; AnsiColor(kGreen); PrintSz("Intellectual"); break;
  873.       }
  874.       AnsiColor(i ? kDefault : kWhite);
  875.  
  876.       /* The biorhythm calculation is below. */
  877.  
  878.       l = RBiorhythm(is.JD, k);
  879.       sprintf(sz, " at %c%3.0f%%", l < 0.0 ? '-' : '+', RAbs(l)); PrintSz(sz);
  880.  
  881.       /* Print smiley face, medium face, or sad face based on current cycle. */
  882.  
  883.       AnsiColor(kPurple);
  884.       sprintf(sz, " :%c", l > 50.0 ? ')' : (l < -50.0 ? '(' : '|'));
  885.       PrintSz(sz);
  886.       AnsiColor(i ? kDefault : kWhite);
  887.       if (j < 3)
  888.         PrintCh(',');
  889.     }
  890.     PrintL();
  891.   }
  892. #endif /* BIORHYTHM */
  893. }
  894.  
  895. /* charts2.c */
  896.